﻿using SmarterCharger.App.Infrastructure;
using SmarterCharger.App.Infrastructure.Interfaces;
using SmarterCharger.App.Model;
using SmarterCharger.Library.Infrastructure;
using SmarterCharger.Library.Infrastructure.Interfaces;
using SmarterCharger.Library.Model;
using SmarterCharger.Library.Repositories.Interfaces;
using System;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Input;

namespace SmarterCharger.App.ViewModel
{
    public class StartChargingBatteryViewModel : ViewModelBase
    {
        private const double DefaultChargeLimit = 80;
        private const double MinimumChargeLimit = 1;
        private const string StartBackgrondTaskErrorTitle = "Bad news";
        private const string StartBackgrondTaskErrorMessage = "Ow, didn't see that one coming:\n\n{0}\n\nCan you get that and try again?";
        private const string SwitchOffSmartPlugErrorTitle = "The smart plug did not switch off";
        private const string SwitchOffSmartPlugErrorMessage = "Tried to switch off smart plug but it didn't want to.\n\n{0}\n\nCan you get that for us?";

        private readonly ISettingsService _settingsService;
        private readonly IBackgroundAgentStarter _backgoundAgentStarter;
        private readonly IMessageBoxService _messageBoxService;
        private readonly ISmartPlugRepository _smartPlugRepository;

        #region Properties

        private SmartPlug _defaultSmartPlug;
        public SmartPlug DefaultSmartPlug 
        {
            get { return _defaultSmartPlug; }
            set
            {
                _defaultSmartPlug = value;
                RaisePropertyChanged("DefaultSmartPlug");
            }
        }

        private double _chargeLimit;
        public double ChargeLimit 
        {
            get { return _chargeLimit; }
            set
            {
                _chargeLimit = value;
                RaisePropertyChanged("ChargeLimit");
            }
        }

        private bool _isLoading;
        public bool IsLoading
        {
            get { return _isLoading; }
            internal set
            {
                _isLoading = value;
                RaisePropertyChanged("IsLoading");
                (ChargeCommand as DelegateCommand).RaiseCanExecuteChanged();
            }
        }

        private bool _isCharging;
        public bool IsCharging
        {
            get { return _isCharging; }
            internal set
            {
                _isCharging = value;
                RaisePropertyChanged("IsCharging");
                (ChargeCommand as DelegateCommand).RaiseCanExecuteChanged();
            }
        }

        #endregion

        public StartChargingBatteryViewModel(ISettingsService settingsService, IBackgroundAgentStarter backgoundAgentStarter,
            IMessageBoxService messageBoxService, ISmartPlugRepository smartPlugRepository)
        {
            if (settingsService == null) throw new ArgumentNullException("settingsService");
            if (backgoundAgentStarter == null) throw new ArgumentNullException("backgoundAgentStarter");
            if (messageBoxService == null) throw new ArgumentNullException("messageBoxService");
            if (smartPlugRepository == null) throw new ArgumentNullException("smartPlugRepository");

            _settingsService = settingsService;
            _backgoundAgentStarter = backgoundAgentStarter;
            _messageBoxService = messageBoxService;
            _smartPlugRepository = smartPlugRepository;

            ChargeCommand = new DelegateCommand(Charge, CanCharge);
        }

        #region ChargeCommand

        public ICommand ChargeCommand { get; private set; }

        private async void Charge(object parameter)
        {
            IsLoading = true;

            var switchResult = await SwitchSmartPlug(isOn: true);
            if (switchResult.StatusCode == HttpStatusCode.NoContent)
            {
                var result = _backgoundAgentStarter.Start();

                if (result.Code == StartBackgrondTaskResultCode.Succeeded)
                    IsCharging = true;
                else
                    _messageBoxService.Show(string.Format(StartBackgrondTaskErrorMessage, result.Code.ToString()), StartBackgrondTaskErrorTitle);
            }
            else
            {
                _messageBoxService.Show(string.Format(StartBackgrondTaskErrorMessage, switchResult.StatusCode.ToString()), StartBackgrondTaskErrorTitle);
            }
            

            IsLoading = false;
        }

        private Task<HttpResponseResult> SwitchSmartPlug(bool isOn)
        {
            var username = _settingsService.GetUsername();
            var password = _settingsService.GetPassword();

            var request = new SwitchSmartPlugRequest 
            { 
                Username=  username,
                Password = password,
                SmartPlugId = DefaultSmartPlug.EnergyDeviceId,
                IsOn = isOn
            };

            return _smartPlugRepository.SwitchSmartPlug(request);
        }

        private bool CanCharge(object parameter)
        {
            return (DefaultSmartPlug != null
                && ChargeLimit >= MinimumChargeLimit
                && !IsLoading
                && !IsCharging);
        }

        #endregion

        public void LoadData()
        {
            //always refresh settings
            IsLoaded = false;

            DefaultSmartPlug = _settingsService.GetDefaultSmartPlug();
            ChargeLimit = _settingsService.GetChargeLimit() ?? DefaultChargeLimit;

            IsLoaded = true;
        }

        public void SaveData()
        {
            _settingsService.UpdateDefaultSmartPlug(DefaultSmartPlug);
            _settingsService.UpdateChargeLimit(ChargeLimit);
        }

        public bool CanCancelCharge()
        {
            return IsCharging;
        }

        public async Task CancelCharge()
        {
            IsLoading = true;

            _backgoundAgentStarter.Stop();

            var switchResult = await SwitchSmartPlug(isOn: false);
            if (switchResult.StatusCode != HttpStatusCode.NoContent)
                _messageBoxService.Show(string.Format(SwitchOffSmartPlugErrorMessage, switchResult.StatusCode), SwitchOffSmartPlugErrorTitle);

            IsCharging = false;
            IsLoading = false;
        }
    }
}